<template>
  <div class="search-form">
    <el-form
      ref="formRef"
      :model="formData"
      :inline="true"
      :label-position="labelPosition"
      :label-width="labelWidth"
      :size="size"
      class="search-form-container"
    >
      <!-- 动态表单项 -->
      <template v-for="item in formItems" :key="item.prop">
        <el-form-item
          v-if="!item.hidden"
          :label="item.label"
          :prop="item.prop"
          :rules="item.rules"
          :class="item.itemClass"
          :style="getItemStyle(item)"
        >
          <!-- 输入框 -->
          <el-input
            v-if="item.type === 'input'"
            v-model="formData[item.prop]"
            :placeholder="item.placeholder || `请输入${item.label}`"
            :disabled="item.disabled"
            :clearable="item.clearable !== false"
            :maxlength="item.maxlength"
            :show-word-limit="item.showWordLimit"
            :prefix-icon="item.prefixIcon"
            :suffix-icon="item.suffixIcon"
            :style="getControlStyle(item)"
            @change="handleFormItemChange(item.prop, formData[item.prop])"
          />

          <!-- 数字输入框 -->
          <el-input-number
            v-else-if="item.type === 'number'"
            v-model="formData[item.prop]"
            :placeholder="item.placeholder || `请输入${item.label}`"
            :disabled="item.disabled"
            :min="item.min"
            :max="item.max"
            :step="item.step || 1"
            :precision="item.precision"
            :controls="item.controls !== false"
            :controls-position="item.controlsPosition"
            @change="handleFormItemChange(item.prop, formData[item.prop])"
          />

          <!-- 下拉选择框 -->
          <el-select
            v-else-if="item.type === 'select'"
            v-model="formData[item.prop]"
            :placeholder="item.placeholder || `请选择${item.label}`"
            :disabled="item.disabled"
            :clearable="item.clearable !== false"
            :multiple="item.multiple"
            :collapse-tags="item.collapseTags"
            :collapse-tags-tooltip="item.collapseTagsTooltip"
            :filterable="item.filterable"
            :class="item.selectClass || item.itemClass"
            :style="{ ...(item.selectStyle || {}), ...getControlStyle(item) }"
            @change="handleFormItemChange(item.prop, formData[item.prop])"
          >
            <el-option
              v-for="option in item.options"
              :key="option.value"
              :label="option.label"
              :value="option.value"
              :disabled="option.disabled"
            />
          </el-select>

          <!-- 级联选择器 -->
          <el-cascader
            v-else-if="item.type === 'cascader'"
            v-model="formData[item.prop]"
            :options="item.options"
            :placeholder="item.placeholder || `请选择${item.label}`"
            :disabled="item.disabled"
            :clearable="item.clearable !== false"
            :show-all-levels="item.showAllLevels !== false"
            :props="item.props"
            :filterable="item.filterable"
            @change="handleFormItemChange(item.prop, formData[item.prop])"
          />

          <!-- 日期选择器 -->
          <el-date-picker
            v-else-if="item.type === 'date'"
            v-model="formData[item.prop]"
            :type="item.dateType || 'date'"
            :placeholder="item.placeholder || `请选择${item.label}`"
            :disabled="item.disabled"
            :clearable="item.clearable !== false"
            :format="item.format"
            :value-format="item.valueFormat"
            :start-placeholder="item.startPlaceholder || '开始日期'"
            :end-placeholder="item.endPlaceholder || '结束日期'"
            :range-separator="item.rangeSeparator || '至'"
            :shortcuts="item.shortcuts"
            :style="getControlStyle(item)"
            @change="handleFormItemChange(item.prop, formData[item.prop])"
          />

          <!-- 时间选择器 -->
          <el-time-picker
            v-else-if="item.type === 'time'"
            v-model="formData[item.prop]"
            :placeholder="item.placeholder || `请选择${item.label}`"
            :disabled="item.disabled"
            :clearable="item.clearable !== false"
            :format="item.format"
            :value-format="item.valueFormat"
            :is-range="item.isRange"
            :range-separator="item.rangeSeparator || '至'"
            :start-placeholder="item.startPlaceholder || '开始时间'"
            :end-placeholder="item.endPlaceholder || '结束时间'"
            @change="handleFormItemChange(item.prop, formData[item.prop])"
          />

          <!-- 开关 -->
          <el-switch
            v-else-if="item.type === 'switch'"
            v-model="formData[item.prop]"
            :disabled="item.disabled"
            :active-text="item.activeText"
            :inactive-text="item.inactiveText"
            :active-value="item.activeValue"
            :inactive-value="item.inactiveValue"
            @change="handleFormItemChange(item.prop, formData[item.prop])"
          />

          <!-- 单选框组 -->
          <el-radio-group
            v-else-if="item.type === 'radio'"
            v-model="formData[item.prop]"
            :disabled="item.disabled"
            @change="handleFormItemChange(item.prop, formData[item.prop])"
          >
            <el-radio
              v-for="option in item.options"
              :key="option.value"
              :label="option.value"
              :disabled="option.disabled"
            >
              {{ option.label }}
            </el-radio>
          </el-radio-group>

          <!-- 复选框组 -->
          <el-checkbox-group
            v-else-if="item.type === 'checkbox'"
            v-model="formData[item.prop]"
            :disabled="item.disabled"
            @change="handleFormItemChange(item.prop, formData[item.prop])"
          >
            <el-checkbox
              v-for="option in item.options"
              :key="option.value"
              :label="option.value"
              :disabled="option.disabled"
            >
              {{ option.label }}
            </el-checkbox>
          </el-checkbox-group>

          <!-- 自定义插槽 -->
          <slot
            v-else-if="item.type === 'slot'"
            :name="item.slotName || item.prop"
            :form-data="formData"
            :item="item"
          ></slot>
        </el-form-item>
      </template>

      <!-- 操作按钮 -->
      <el-form-item>
        <div class="search-form-buttons">
          <el-button type="primary" :icon="Search" @click="handleSearch" :loading="loading">
            {{ searchButtonText }}
          </el-button>
          <el-button :icon="Refresh" @click="handleReset">
            {{ resetButtonText }}
          </el-button>
          <slot name="buttons"></slot>
        </div>
      </el-form-item>
    </el-form>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, watch, onMounted } from 'vue';
import { Search, Refresh } from '@element-plus/icons-vue';
import type { FormInstance } from 'element-plus';

export interface FormItemOption {
  label: string;
  value: any;
  disabled?: boolean;
}

export interface FormItem {
  type:
    | 'input'
    | 'number'
    | 'select'
    | 'cascader'
    | 'date'
    | 'time'
    | 'switch'
    | 'radio'
    | 'checkbox'
    | 'slot';
  label: string;
  prop: string;
  placeholder?: string;
  disabled?: boolean;
  clearable?: boolean;
  hidden?: boolean;
  rules?: any[];
  options?: FormItemOption[];
  // input
  maxlength?: number;
  showWordLimit?: boolean;
  prefixIcon?: string;
  suffixIcon?: string;
  // number
  min?: number;
  max?: number;
  step?: number;
  precision?: number;
  controls?: boolean;
  controlsPosition?: 'right' | '';
  // select
  multiple?: boolean;
  collapseTags?: boolean;
  collapseTagsTooltip?: boolean;
  filterable?: boolean;
  // cascader
  showAllLevels?: boolean;
  props?: any;
  // date
  dateType?:
    | 'date'
    | 'week'
    | 'month'
    | 'year'
    | 'datetime'
    | 'datetimerange'
    | 'daterange'
    | 'monthrange';
  format?: string;
  valueFormat?: string;
  startPlaceholder?: string;
  endPlaceholder?: string;
  rangeSeparator?: string;
  shortcuts?: any[];
  // time
  isRange?: boolean;
  // switch
  activeText?: string;
  inactiveText?: string;
  activeValue?: any;
  inactiveValue?: any;
  // slot
  slotName?: string;
  // 样式相关属性（通用）
  width?: string | number; // 宽度，如 '200px' 或 200
  minWidth?: string | number; // 最小宽度
  itemClass?: string; // 表单项自定义类名
  itemStyle?: Record<string, any>; // 表单项自定义样式
  // 兼容旧版
  selectClass?: string;
  selectStyle?: Record<string, any>;
}

interface Props {
  formItems: FormItem[];
  initialValues?: Record<string, any>;
  labelPosition?: 'top' | 'left' | 'right';
  labelWidth?: string | number;
  size?: 'large' | 'default' | 'small';
  searchButtonText?: string;
  resetButtonText?: string;
  loading?: boolean;
  autoSearch?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  formItems: () => [],
  initialValues: () => ({}),
  labelPosition: 'right',
  labelWidth: '120px',
  size: 'default',
  searchButtonText: '搜索',
  resetButtonText: '重置',
  loading: false,
  autoSearch: false
});

const emit = defineEmits<{
  (e: 'search', formData: Record<string, any>): void;
  (e: 'reset'): void;
  (e: 'change', prop: string, value: any): void;
}>();

// 表单引用
const formRef = ref<FormInstance>();

// 表单数据
const formData = reactive<Record<string, any>>({});

// 初始化表单数据
const initFormData = () => {
  // 清空表单数据
  Object.keys(formData).forEach(key => {
    delete formData[key];
  });

  // 根据formItems初始化表单数据
  props.formItems.forEach(item => {
    const initialValue = props.initialValues[item.prop];

    // 设置初始值
    if (initialValue !== undefined) {
      formData[item.prop] = initialValue;
    } else {
      // 根据类型设置默认值
      switch (item.type) {
        case 'checkbox':
          formData[item.prop] = [];
          break;
        case 'switch':
          formData[item.prop] = false;
          break;
        default:
          formData[item.prop] = '';
      }
    }
  });
};

// 监听initialValues变化
watch(
  () => props.initialValues,
  () => {
    initFormData();
  },
  { deep: true }
);

// 处理表单项变化
const handleFormItemChange = (prop: string, value: any) => {
  emit('change', prop, value);

  // 如果开启自动搜索，则触发搜索
  if (props.autoSearch) {
    handleSearch();
  }
};

// 处理搜索
const handleSearch = () => {
  formRef.value?.validate(valid => {
    if (valid) {
      emit('search', { ...formData });
    }
  });
};

// 处理重置
const handleReset = () => {
  formRef.value?.resetFields();
  initFormData();
  emit('reset');

  // 如果开启自动搜索，则触发搜索
  if (props.autoSearch) {
    handleSearch();
  }
};

// 获取表单项样式
const getItemStyle = (item: FormItem) => {
  return item.itemStyle || {};
};

// 获取控件样式（input、select、date 等）
const getControlStyle = (item: FormItem) => {
  const style: Record<string, any> = {};

  if (item.width) {
    style.width = typeof item.width === 'number' ? `${item.width}px` : item.width;
  } else {
    // 设置默认宽度
    style.width = '200px';
  }

  if (item.minWidth) {
    style.minWidth = typeof item.minWidth === 'number' ? `${item.minWidth}px` : item.minWidth;
  }

  return style;
};

// 组件挂载时初始化表单数据
onMounted(() => {
  initFormData();
});
</script>

<style lang="scss" scoped>
.search-form {
  width: 100%;
  margin-bottom: 20px;
  background-color: var(--theme-module-bg);
  padding: 20px;
  border-radius: 4px;

  .search-form-container {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
  }

  .search-form-buttons {
    display: flex;
    gap: 10px;
  }

  // 主题适配样式
  :deep(.el-input__wrapper) {
    background-color: var(--theme-element-bg);
    box-shadow: none !important;
    border: 1px solid var(--form-input-border-color) !important;

    &:hover {
      border-color: var(--theme-color-primary) !important;
    }

    &.is-focus {
      border-color: var(--theme-color-primary) !important;
      box-shadow: none !important;
    }
  }

  :deep(.el-input__inner) {
    color: var(--theme-text-color);
  }

  :deep(.el-select__wrapper) {
    background-color: var(--theme-element-bg);
    box-shadow: none !important;
    border: 1px solid var(--form-input-border-color) !important;

    &:hover {
      border-color: var(--el-color-primary) !important;
    }

    &.is-focus {
      border-color: var(--el-color-primary) !important;
      box-shadow: none !important;
    }
  }

  :deep(.el-date-editor) {
    --el-date-editor-width: auto;

    .el-range-input {
      background-color: var(--input-bg-color);
      color: var(--theme-text-color);
    }

    .el-range-separator {
      color: var(--select-placeholder-color);
    }
  }

  :deep(.el-input__wrapper.is-focus),
  :deep(.el-select__wrapper.is-focus) {
    box-shadow: none !important;
  }
}
</style>
